package points

import (
	"context"
	"encoding/json"
	"net/url"
	"sale-admin/config"
	"sale-admin/config/mysql"
	"sale-admin/config/redis"
	"sale-admin/internal/dao"
	"sale-admin/internal/define"
	"sale-admin/internal/models"
	"strconv"
	"strings"
	"time"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
	"github.com/samber/lo"
	"gorm.io/gorm"
)

type MallcooPoints struct {
	PointsInterface
}

const (
	MALLCOO_SUCCESS = "PUB-00000"
	// 公共参数
	MY_IS_PROD           = false // 是否生产环境
	MY_URL_TEST          = "https://openapi10.mallcoo.cn"
	MY_URL_PROD          = "https://openapi10.mallcoo.cn"
	MY_HEADER_APPID      = "AppID"     // appId
	MY_HEADER_PUBLIC_KEY = "PublicKey" // appId
	MY_HEADER_TIME_STAMP = "TimeStamp" // appId
	MY_HEADER_SIGN       = "Sign"      // 签名
)

// 3 会员查询
type MallcooMemberQueryReq MallcooCommonReq
type MallcooMemberQueryRsp struct {
	Code    int    `json:"code"` // 200成功，其他失败
	Message string `json:"message"`
	Data    struct {
		OpenUserID        string  `json:"OpenUserID"`        // 用户ID
		NickName          string  `json:"NickName"`          // 用户昵称
		Avatar            string  `json:"Avatar"`            // 会员昵称
		HeadImgUrl        string  `json:"HeadImgUrl"`        // 头像地址
		Mobile            string  `json:"Mobile"`            // 手机号码
		WXOpenID          string  `json:"WXOpenID"`          // 微信OpenID
		UserToken         string  `json:"UserToken"`         // 用户Token
		Score             float64 `json:"Score"`             // 积分
		MallCardTypeID    int64   `json:"MallCardTypeID"`    // 猫酷会员卡类型ID
		MallCardNo        string  `json:"MallCardNo"`        // 猫酷会员卡号
		MallCardName      string  `json:"MallCardName"`      // 猫酷会员卡名称
		ThirdPartyCardNo  string  `json:"ThirdPartyCardNo"`  // 第三方会员ID
		UserCreateTime    string  `json:"UserCreateTime"`    //
		MallCardApplyTime string  `json:"MallCardApplyTime"` //
	} `json:"data"`
}

// body:  `{"flowNo":"011810240004","creditType":"1","tranMode":"0","billGoodsList":[{"goodsCode":"201000002","goodsName":"上衣","goodsCount":"1","price":"8"}],"billPayList":[{"paymentTypeCode":"01","paymentTypeName":"现金","paymentNo":"1","paymentAmount":"8","changeAmount":"0"}],"realAmt":"8","srcAmt":"8","favAmt":"2","invoiceAmt":"8","cardId":"880600008086","shopId":"2011809020001","userAccount":"000","posNo":"01","filDate":"2018-10-24 10:25:25","exceptionRefund":"1","rebatePoint":"8","totalPoint":"24290","isRefunded":""}`

// GetSign 获取签名
// queryMap query字段
// params body字段
func (MallcooPoints) GetQueryStringOld(ctx context.Context, SalesID string, queryMap map[string]string, params *string) (queryString string, err error) {
	accessToken, err1 := MallcooPoints{}.GetAccessToken(ctx, SalesID)
	if err1 != nil {
		logx.Error(ctx, "mallcoo get access token", logx.Any("error", err1))
		return "", err1
	}
	rnd, _ := helper.UUID{}.String()
	timestamp := time.Now().Unix()

	var URL url.URL
	query := URL.Query()
	query.Add("accessToken", accessToken)
	query.Add("rnd", rnd)
	// query.Add("appKey", config.Config.MallcooPoints.APPKey)
	if params != nil {
		query.Add("body", *params)
	}
	query.Add("timestamp", strconv.Itoa(int(timestamp)))
	if len(queryMap) > 0 {
		for key, val := range queryMap {
			query.Add(key, val)
		}
	}

	md5String := "" //helper.Md5(queryString + config.Config.MallcooPoints.APPSecret)
	if params != nil {
		query.Del("body") //body参与签名但不拼接queryString
	}
	queryString = query.Encode() + "&sign=" + strings.ToUpper(md5String) + "&signType=md5"
	return queryString, nil
}

// [获取基础配置 TimeStamp]
func getTimeStamp() string {
	currentTime := time.Now()
	return currentTime.Format("20060102150405") // return a
}

// 生成: Mallcoo签名 规则：将publicKey、timeStamp、data、privateKey按顺序拼接成字符串JsonData。例：{publicKey:aaa,timeStamp:bbb,data:{...},privateKey:ddd}
func GetSign(Data string) (sign string, stringTime string) {
	//拼接所需的字符串
	var jsonData string
	stringTime = getTimeStamp()
	jsonData = "{publicKey:" + config.Config.MallcooPoints.PublicKey +
		",timeStamp:" + stringTime +
		",data:" + Data +
		// ",privateKey:" + MY_KEYWORDS_PRIVATE_KEY + "}"
		",privateKey:" + config.Config.MallcooPoints.PrivateKey + "}"
	// md5加密
	md5String := helper.Md5(jsonData)
	// 返回低8-16中间的字符
	return strings.ToUpper(lo.Substring(md5String, 8, 16)), stringTime // 截取
}

type MallcooDeviceLoginRsp struct {
	ErrorCode    string      `json:"errorCode"`
	ErrorMessage string      `json:"errorMessage"`
	ErrorCodeMsg interface{} `json:"errorCodeMsg"`
	Extra        interface{} `json:"extra"`
	Display      bool        `json:"display"`
	Exception    interface{} `json:"exception"`
	ReqTime      int         `json:"reqTime"`
	CostTime     int         `json:"costTime"`
	SkipType     interface{} `json:"skipType"`
	ServiceTime  int         `json:"serviceTime"`
	SkipParam    interface{} `json:"skipParam"`
	Body         MallcooBody `json:"body"`
	Encrypted    bool        `json:"encrypted"`
}
type MallcooBody struct {
	WorkKey                string `json:"workKey"`
	AccessToken            string `json:"accessToken"`
	RegisterTime           int    `json:"registerTime"`
	SessionValiditySeconds int    `json:"sessionValiditySeconds"`
}

func NewMallcooPoints() PointsInterface {
	return &MallcooPoints{}
}

// 设备登陆
// 获取accessToken
func (MallcooPoints) GetAccessToken(ctx context.Context, SalesID string) (accessToken string, err error) {
	rdb := redis.NewDB()
	AccessToken, err1 := rdb.HGet(ctx, define.RedisMallcooPointsAccessToken, SalesID).Result()
	if AccessToken != "" && err1 == nil {
		return AccessToken, nil
	}

	// 重新登录
	rnd, _ := helper.UUID{}.String()

	var URL url.URL
	query := URL.Query()
	query.Add("deviceId", SalesID)
	// query.Add("appKey", config.Config.MallcooPoints.APPKey)
	query.Add("rnd", rnd)
	PostURL := config.Config.MallcooPoints.BaseURL + "/api/v3/securities/devices/register?" + query.Encode()

	statusCode, bytes, err := helper.Net{}.Request(ctx, "POST", PostURL, map[string]string{}, nil)
	var res MallcooDeviceLoginRsp
	json.Unmarshal(bytes, &res)
	logx.Error(ctx, "mallcoo devices register", logx.Any("url", PostURL), logx.Any("res", res), logx.Any("statusCode", statusCode), logx.Any("err", err))
	if statusCode != 200 || err != nil {
		return "", errorx.New("设备登录错误", -1)
	}
	if res.ErrorCode != MALLCOO_SUCCESS {
		return "", errorx.New(res.ErrorMessage, -1)
	}
	//写入缓存
	rdb.HSet(ctx, define.RedisMallcooPointsAccessToken, SalesID, res.Body.AccessToken)
	rdb.Expire(ctx, define.RedisMallcooPointsAccessToken, time.Duration(res.Body.SessionValiditySeconds/2)*time.Second)
	return res.Body.AccessToken, nil
}

type MallcooCommonReqPre struct {
	Code    int    `json:"Code"`
	Message string `json:"Message"`
}

type MallcooCommonReq struct {
	ErrorCode    string      `json:"errorCode"`
	ErrorMessage string      `json:"errorMessage"`
	ErrorCodeMsg string      `json:"errorCodeMsg"`
	Extra        interface{} `json:"extra"`
	Display      bool        `json:"display"`
	Exception    interface{} `json:"exception"`
	ReqTime      int         `json:"reqTime"`
	CostTime     int         `json:"costTime"`
	SkipType     interface{} `json:"skipType"`
	ServiceTime  int         `json:"serviceTime"`
	SkipParam    interface{} `json:"skipParam"`
	Encrypted    bool        `json:"encrypted"`
}

type MallcooGetMemberInfoRsp struct {
	MallcooCommonReq
	Body MallcooMemberInfoBody `json:"body"`
}

type MallcooMemberInfoLevel struct {
	ID                           string      `json:"id"`
	Code                         string      `json:"code"`
	Name                         string      `json:"name"`
	Icon                         string      `json:"icon"`
	LevelType                    string      `json:"levelType"`
	LevelLabel                   interface{} `json:"levelLabel"`
	MostBindCarPlateCount        int         `json:"mostBindCarPlateCount"`
	LeftBindCarPlateCount        interface{} `json:"leftBindCarPlateCount"`
	CanBindCarPlate              bool        `json:"canBindCarPlate"`
	SkinID                       interface{} `json:"skinId"`
	SkinImgURL                   interface{} `json:"skinImgUrl"`
	SkinName                     interface{} `json:"skinName"`
	Level                        int         `json:"level"`
	BindCarPlateTimeCycle        string      `json:"bindCarPlateTimeCycle"`
	BindCarPlateTimesInCycle     int         `json:"bindCarPlateTimesInCycle"`
	LeftBindCarPlateTimesInCycle interface{} `json:"leftBindCarPlateTimesInCycle"`
}
type MallcooMemberInfoBody struct {
	ID                              string                 `json:"id"`                  //会员ID
	CardID                          interface{}            `json:"cardId"`              //会员卡id
	Name                            interface{}            `json:"name"`                //会员姓名
	Gender                          int                    `json:"gender"`              //性别 0未知 1男 2女
	Phone                           string                 `json:"phone"`               //手机号码
	Birthday                        string                 `json:"birthday"`            //生日
	NickName                        string                 `json:"nickName"`            //会员昵称
	HeadImg                         string                 `json:"headImg"`             //头像
	Level                           MallcooMemberInfoLevel `json:"level"`               //会员级别
	CouponCount                     int                    `json:"couponCount"`         //拥有的优惠券数量
	CaredCount                      int                    `json:"caredCount"`          //关注的商户数量
	NormalCouponCount               int                    `json:"normalCouponCount"`   //未使用的优惠券数量
	Credit                          string                 `json:"credit"`              //【【【【【【【【【【积分账户余额】】】】】】】】】】
	EwalletBalance                  string                 `json:"ewalletBalance"`      //储值账户余额
	BindCrmVipcard                  bool                   `json:"bindCrmVipcard"`      //是否绑定会员卡
	CardNo                          string                 `json:"cardNo"`              //会员卡号
	CrmVipcardStatus                int                    `json:"crmVipcardStatus"`    //会员卡状态 15未开通 20正常 30已禁用 40已挂失 60已注销 70冻结
	CarPlate                        string                 `json:"carPlate"`            //车牌号
	MallInfo                        interface{}            `json:"mallInfo"`            //门店信息
	MallID                          string                 `json:"mallId"`              //门店id
	Job                             string                 `json:"job"`                 //职业
	ParkingTicketCount              int                    `json:"parkingTicketCount"`  //停车券数量
	NewsCount                       int                    `json:"newsCount"`           //未读信息数量
	HasSigned                       bool                   `json:"hasSigned"`           //是否签到
	NeedMoreInfo                    bool                   `json:"needMoreInfo"`        //注册所需的信息是否填写
	OpenIds                         interface{}            `json:"openIds"`             //openid列表
	OpenIDSources                   interface{}            `json:"openIdSources"`       //openid来源列表  source：portal_weixin 微信公众号，portal_web 网页用户端	mini_weixin 微信小程序	app_ios 苹果用户端app_android 安卓用户端
	InfoIsCompleted                 bool                   `json:"infoIsCompleted"`     //是否完善资料所需的信息字段
	DeliveryAddressList             []interface{}          `json:"deliveryAddressList"` //会员邮寄收货地址列表
	CrmVipcardStatusText            interface{}            `json:"crmVipcardStatusText"`
	Hobbies                         []interface{}          `json:"hobbies"`
	OpenID                          interface{}            `json:"openId"`
	CarPlateList                    []interface{}          `json:"carPlateList"`
	Address                         interface{}            `json:"address"`
	IDCard                          interface{}            `json:"idCard"`
	ParkingPaymentPattern           interface{}            `json:"parkingPaymentPattern"`
	UnionID                         interface{}            `json:"unionId"`
	QrCode                          interface{}            `json:"qrCode"`
	MemberAutoParkingPayMandateList []interface{}          `json:"memberAutoParkingPayMandateList"`
	ExtendInfos                     []interface{}          `json:"extendInfos"`
	Email                           interface{}            `json:"email"`
	CreditExpireDate                interface{}            `json:"creditExpireDate"`
	LevelStartTime                  interface{}            `json:"levelStartTime"`
	LevelEndTime                    interface{}            `json:"levelEndTime"`
	AlipayUserID                    interface{}            `json:"alipayUserId"`
	AlipayUserIDList                interface{}            `json:"alipayUserIdList"`
	LogoutTag                       interface{}            `json:"logoutTag"`
	CardValidDate                   interface{}            `json:"cardValidDate"`
	MemberChildrenInfo              interface{}            `json:"memberChildrenInfo"`
	CanModifyBirthday               interface{}            `json:"canModifyBirthday"`
	LatelyCheckTime                 interface{}            `json:"latelyCheckTime"`
	SubscribeNoteRemind             interface{}            `json:"subscribeNoteRemind"`
	PopMessageList                  interface{}            `json:"popMessageList"`
	BehaviorInfo                    interface{}            `json:"behaviorInfo"`
	UnlicensedCar                   interface{}            `json:"unlicensedCar"`
	HasEshopOrder                   interface{}            `json:"hasEshopOrder"`
	MemberDiscountInfo              interface{}            `json:"memberDiscountInfo"`
	GrowUp                          interface{}            `json:"growUp"`
	ByteDanceOpenID                 interface{}            `json:"byteDanceOpenId"`
	ByteDanceOpenIds                interface{}            `json:"byteDanceOpenIds"`
	ByteDanceUnionID                interface{}            `json:"byteDanceUnionId"`
	AutonymStatus                   int                    `json:"autonymStatus"`
	MarriageStatus                  string                 `json:"marriageStatus"`
	IsOpenCard                      bool                   `json:"isOpenCard"`
	LevelIsNew                      bool                   `json:"levelIsNew"`
	UpgradeProgress                 string                 `json:"upgradeProgress"`
	HavePayPassword                 bool                   `json:"havePayPassword"`
	CmbcJointMember                 bool                   `json:"cmbcJointMember"`
	MinPayNoPassword                int                    `json:"minPayNoPassword"`
	UseMemberBenefits               bool                   `json:"useMemberBenefits"`
	WillExpireCredit                string                 `json:"willExpireCredit"`
	HisCredit                       string                 `json:"hisCredit"`
	CurrentTime                     int                    `json:"currentTime"`
	ParkingPaymentStatus            int                    `json:"parkingPaymentStatus"`
	ExternalCouponCount             int                    `json:"externalCouponCount"`
	CreditCardCount                 int                    `json:"creditCardCount"`
	CanUseCreditCardCount           int                    `json:"canUseCreditCardCount"`
	CountingCardCount               string                 `json:"countingCardCount"`
	CanUseCountingCardCount         int                    `json:"canUseCountingCardCount"`
	GrowUpBalance                   string                 `json:"growUpBalance"`
	ActivateTime                    int                    `json:"activateTime"`
	RegTime                         string                 `json:"regTime"`
	CardTypeName                    string                 `json:"cardTypeName"`
	CurrentAddedCredit              string                 `json:"currentAddedCredit"`
	CreditAccountTotalRecharge      string                 `json:"creditAccountTotalRecharge"`
	JoinedCard                      bool                   `json:"joinedCard"`
	FirstOrder                      bool                   `json:"firstOrder"`
	Logout                          bool                   `json:"logout"`
	PopMessage                      bool                   `json:"popMessage"`
}

func getUrl() string {
	return MY_URL_TEST
}

// [获取基础配置 AppID]
func getAppID() string {
	// return MY_KEYWORDS_APPID
	return config.Config.MallcooPoints.APPID
}

// [获取基础配置 PublicKey]
func getPublicKey() string {
	// return MY_KEYWORDS_PUBLIC_KEY
	return config.Config.MallcooPoints.PublicKey
}

// 构建请求头
func buildHeader(sign, stringTime string) map[string]string {
	header := make(map[string]string) // 格式都是字符串
	header["Content-Type"] = "application/json"
	header["AppID"] = getAppID()
	header["PublicKey"] = getPublicKey()
	header["TimeStamp"] = stringTime
	header["Sign"] = sign
	return header
}

// 4.0 根据 【Tiket】 获取UserToken
func (MallcooPoints) GetUserToken(ctx context.Context, db *gorm.DB, openID string) (
	data MemberMsg,
	err error,
) {
	// 通过OpenID获取当前的Ticket
	MallcooTicket := ""
	WechatUserInfo, _ := dao.WechatUser{}.Detail(ctx, db, "", openID)
	if WechatUserInfo.MallcooTicket != "" {
		MallcooTicket = WechatUserInfo.MallcooTicket
	}
	// GetToken ByTicket
	QueryURL := getUrl() + "/User/OAuth/v1/GetToken/ByTicket/"
	params := make(map[string]string)
	params["Ticket"] = MallcooTicket
	// 组装JSON字符串
	bytes, _ := json.Marshal(params) // 类似json_encode
	// 组装数组
	var PostData map[string]interface{}
	json.Unmarshal(bytes, &PostData) // 类似json_decode 变数组
	// 获取签名
	sign, stringTime := GetSign(string(bytes))

	// 组装Header
	header := buildHeader(sign, stringTime)
	statusCode, bytes, err := helper.Net{}.Request(ctx, "POST", QueryURL, header, params)

	var rsp MemberMsg
	// 定义请求结构体
	var res MallcooMemberQueryRsp
	json.Unmarshal(bytes, &res)
	if statusCode != 200 || res.Code != 1 || err != nil {
		return rsp, errorx.New(res.Message, int(res.Code))
	}

	rsp.NickName = res.Data.NickName
	rsp.Points = res.Data.Score
	rsp.HeadImg = res.Data.HeadImgUrl
	rsp.Phone = res.Data.Mobile
	rsp.ID = res.Data.OpenUserID
	// 写入数据库
	if rsp.ID != "" {
		db.Model(&models.MaWechatUser{}).
			Where("open_id = ?", openID).
			UpdateColumn("user_id", rsp.ID)
	}
	rsp.CardNo = res.Data.MallCardNo
	rsp.UserToken = res.Data.UserToken

	return rsp, nil
}

// 4.2 根据 【手机号】 查询会员资料
func (MallcooPoints) GetMemberInfo(ctx context.Context, db *gorm.DB, SalesID, phone, openID string) (
	data MemberMsg,
	err error,
) {

	// 通过UserToken获取会员信息
	info, _ := MallcooPoints{}.GetUserToken(context.Background(), db, openID)
	UserToken := ""
	QueryURL := ""
	params := make(map[string]string)

	if info.UserToken != "" {
		UserToken = info.UserToken
		// QueryURL := getUrl() + "/User/AdvancedInfo/v1/GetMemberInfo/ByMobile/"
		// params["Mobile"] = phone
		QueryURL = getUrl() + "/User/AdvancedInfo/v1/Get/ByToken/"
		params["UserToken"] = UserToken
	} else {
		// 通过OpenUserID获取
		WechatUserInfo, _ := dao.WechatUser{}.Detail(ctx, db, "", openID)
		if WechatUserInfo.UserID != "" {
			// 通过OpenUserID 获取猫酷的会员信息
			QueryURL = getUrl() + "/User/AdvancedInfo/v1/Get/ByOpenUserID"
			params["OpenUserID"] = WechatUserInfo.UserID
		}
	}

	// 组装JSON字符串
	bytes, _ := json.Marshal(params) // 类似json_encode
	// 组装数组
	var PostData map[string]interface{}
	json.Unmarshal(bytes, &PostData) // 类似json_decode 变数组
	// 获取签名
	sign, stringTime := GetSign(string(bytes))

	// 组装Header
	header := buildHeader(sign, stringTime)
	statusCode, bytes, err := helper.Net{}.Request(ctx, "POST", QueryURL, header, params)

	var rsp MemberMsg
	// 定义请求结构体
	var res MallcooMemberQueryRsp
	json.Unmarshal(bytes, &res)
	if statusCode != 200 || res.Code != 1 || err != nil {
		return rsp, errorx.New(res.Message, int(res.Code))
	}

	rsp.NickName = res.Data.NickName
	rsp.Points = res.Data.Score
	rsp.HeadImg = res.Data.HeadImgUrl
	rsp.Phone = res.Data.Mobile
	rsp.ID = res.Data.OpenUserID
	rsp.CardNo = res.Data.MallCardNo

	return rsp, nil
}

// 4.2 根据 【手机号】 查询会员资料
func (MallcooPoints) GetMemberInfoOld(ctx context.Context, db *gorm.DB, SalesID, phone, openid string) (
	data MemberMsg,
	err error,
) {

	// 通过UserToken获取用户信息

	QueryURL := getUrl() + "/User/AdvancedInfo/v1/GetMemberInfo/ByMobile/"

	params := make(map[string]string)
	params["Mobile"] = phone
	// 组装JSON字符串
	bytes, _ := json.Marshal(params) // 类似json_encode
	// 组装数组
	var PostData map[string]interface{}
	json.Unmarshal(bytes, &PostData) // 类似json_decode 变数组
	// 获取签名
	sign, stringTime := GetSign(string(bytes))

	// 组装Header
	header := buildHeader(sign, stringTime)
	statusCode, bytes, err := helper.Net{}.Request(ctx, "POST", QueryURL, header, params)

	var rsp MemberMsg
	// 定义请求结构体
	var res MallcooMemberQueryRsp
	json.Unmarshal(bytes, &res)
	if statusCode != 200 || res.Code != 1 || err != nil {
		return rsp, errorx.New(res.Message, int(res.Code))
	}

	rsp.NickName = res.Data.NickName
	rsp.Points = res.Data.Score
	rsp.HeadImg = res.Data.HeadImgUrl
	rsp.Phone = res.Data.Mobile
	rsp.ID = res.Data.OpenUserID
	rsp.CardNo = res.Data.MallCardNo

	return rsp, nil
}

type MallcooMallInfo struct {
	ID          string      `json:"id"`
	Code        string      `json:"code"`
	Name        string      `json:"name"`
	Icon        interface{} `json:"icon"`
	NameInitial interface{} `json:"nameInitial"`
	TypeID      interface{} `json:"typeId"`
	TypeName    interface{} `json:"typeName"`
}

type MallcooBalanceQueryRsp struct {
	MallcooCommonReq
	Body MallcooBalanceQueryBody `json:"body"`
}
type MallcooBalanceQueryBody struct {
	MemberID      string      `json:"memberId"`      //会员ID
	CardNo        string      `json:"cardNo"`        //会员卡号
	Point         string      `json:"point"`         //会员积分
	PointString   string      `json:"pointString"`   //会员积分
	Balance       int         `json:"balance"`       //会员储值余额，单位分
	BalanceString interface{} `json:"balanceString"` //会员储值余额
	CardType      string      `json:"cardType"`      // member -- 会员卡
}

// 4.3 PointsQuery 积分余额查询
func (MallcooPoints) PointsQuery(ctx context.Context, SalesID, openid, mallId string) (points float64, err error) {
	db := mysql.NewDB()
	var WechatUserInfo models.MaWechatUser
	var WechatUserCount int64
	db.Model(&models.MaWechatUser{}).
		Where("open_id = ?", openid).
		Take(&WechatUserInfo).
		Count(&WechatUserCount)
	if WechatUserCount == 0 {
		err = errorx.New("【猫酷】当前用户未注册", 100099)
		return
	}
	// 验证正弘系统会否注册用户
	memberRsp, err := MallcooPoints{}.GetMemberInfo(ctx, db, SalesID, WechatUserInfo.Phone, WechatUserInfo.OpenID)
	if memberRsp.ID == "" || err != nil {
		err = errorx.New("【猫酷】当前用户未注册", 100099)
		return
	}
	return memberRsp.Points, nil
}

// 4.4 BalanceTrade 积分余额支付
// SalesID             //必填 机器码
// cardNo              //必填 会员卡号
// tradeType           //必填 交易类型 recharge 增加 consume 扣减 revoke 冲正
// tradeAmount         //必填 交易数额 积分值 最多保留两位小数 (recharge 正数 consume 负数)
// clientTradeSn       //必填 客户端交易编号 不超过32位字符串
// originClientTradeSn //选填 原客户端交易编号 冲正时必填
// mallId              //条件可选，视现场需求而定
func (MallcooPoints) PointsConsume(
	ctx context.Context,
	db *gorm.DB,
	salesID,
	openid,
	clientTradeSn string,
	tradeAmount float64,
	mallId string,
) (
	err error,
) {
	// 查询微信用户是否存在
	var WechatUserInfo models.MaWechatUser
	var WechatUserCount int64
	mysql.NewDB().Model(&models.MaWechatUser{}).
		Where("open_id = ?", openid).
		Take(&WechatUserInfo).
		Count(&WechatUserCount)
	if WechatUserCount == 0 || WechatUserInfo.Phone == "" {
		err = errorx.New("【猫酷】当前用户未注册", 100099)
		return
	}
	// 验证猫酷系统会员是否注册用户
	memberRsp, err := MallcooPoints{}.GetMemberInfo(ctx, db, salesID, WechatUserInfo.Phone, WechatUserInfo.OpenID)
	if memberRsp.ID == "" || err != nil {
		err = errorx.New("【猫酷】当前用户未注册", 100099)
		return
	}

	if clientTradeSn == "" {
		return errorx.New("客户端交易编号不能为空", -1)
	}
	QueryURL := getUrl() + "/User/Score/v1/Subtract/ByOpenUserID/"
	var PostData = make(map[string]interface{})
	PostData["OpenUserId"] = memberRsp.ID // 手机号
	PostData["ScoreEvent"] = 1001         // 积分消费
	PostData["Score"] = -tradeAmount      // 扣除的积分
	// PostData["Score"] = tradeAmount     // 扣除的积分
	PostData["TransID"] = clientTradeSn // 内部订单号

	bytes, _ := json.Marshal(&PostData) // 类似json_encode

	// 获取签名
	sign, stringTime := GetSign(string(bytes))

	// 组装Header
	header := buildHeader(sign, stringTime)

	// 开启请求接口
	statusCode, bytes, err := helper.Net{}.Request(ctx, "POST", QueryURL, header, PostData)

	// 定义猫酷接口返回参数
	var rsp MallcooCommonReqPre
	json.Unmarshal(bytes, &rsp)
	logx.Info(ctx, "balance trade", logx.Any("queryURL", QueryURL), logx.Any("PostData", PostData), logx.Any("statusCode", statusCode), logx.Any("bytes", string(bytes)), logx.Any("err", err))
	if rsp.Code != 1 {
		err = errorx.New(rsp.Message)
		return
	}
	return nil
}

// 增加积分
// SalesID             //必填 机器码
// cardNo              //必填 会员卡号
// tradeType           //必填 交易类型 recharge 增加 consume 扣减 revoke 冲正
// tradeAmount         //必填 交易数额 积分值 最多保留两位小数 (recharge 正数 consume 负数)
// clientTradeSn       //必填 客户端交易编号 不超过32位字符串
// originClientTradeSn //选填 原客户端交易编号 冲正时必填
// mallId              //条件可选，视现场需求而定
func (MallcooPoints) PointsReverse(
	ctx context.Context,
	db *gorm.DB,
	salesID,
	openid,
	refundOrderID string, // 退款单号
	clientTradeSn string, // 订单号
	tradeAmount float64,
	mallId string,
) (
	err error,
) {
	// 查询微信用户是否存在
	var WechatUserInfo models.MaWechatUser
	var WechatUserCount int64
	mysql.NewDB().Model(&models.MaWechatUser{}).
		Where("open_id = ?", openid).
		Take(&WechatUserInfo).
		Count(&WechatUserCount)
	if WechatUserCount == 0 || WechatUserInfo.Phone == "" {
		err = errorx.New("【猫酷】当前用户未注册", 100099)
		return
	}
	// 验证猫酷系统会员是否注册用户
	memberRsp, err := MallcooPoints{}.GetMemberInfo(ctx, db, salesID, WechatUserInfo.Phone, WechatUserInfo.OpenID)
	if memberRsp.ID == "" || err != nil {
		err = errorx.New("【猫酷】当前用户未注册", 100099)
		return
	}

	if clientTradeSn == "" {
		return errorx.New("客户端交易编号不能为空", -1)
	}
	// 增加积分
	QueryURL := getUrl() + "/User/Score/v1/Plus/ByOpenUserID/"
	var PostData = make(map[string]interface{})
	PostData["OpenUserId"] = memberRsp.ID // 手机号
	PostData["ScoreEvent"] = 2102         // 退货退积分
	PostData["Score"] = tradeAmount       // 增加的积分
	PostData["TransID"] = refundOrderID   // 内部订单号,唯一保证不会重复

	bytes, _ := json.Marshal(&PostData) // 类似json_encode

	// 获取签名
	sign, stringTime := GetSign(string(bytes))

	// 组装Header
	header := buildHeader(sign, stringTime)

	// 开启请求接口
	statusCode, bytes, err := helper.Net{}.Request(ctx, "POST", QueryURL, header, PostData)

	// 定义猫酷接口返回参数
	var rsp MallcooCommonReqPre
	json.Unmarshal(bytes, &rsp)
	logx.Info(ctx, "balance trade", logx.Any("queryURL", QueryURL), logx.Any("PostData", PostData), logx.Any("statusCode", statusCode), logx.Any("bytes", string(bytes)), logx.Any("err", err))
	if rsp.Code != 1 {
		err = errorx.New(rsp.Message)
		return
	}
	return nil
}

// 4.1 MemberRegist 会员注册
// phone 必填
func (MallcooPoints) MemberRegist(
	ctx context.Context,
	db *gorm.DB,
	SalesID,
	mallID,
	phone, // 只需要这个就行
	name string, gender int, birthday, idCard, Openid,
	headImg, provinceId, cityId, areaId, address string,
) (
	err error,
) {
	QueryURL := getUrl() + "/User/MallCard/v1/Open/ByMobile/"
	params := make(map[string]string)
	params["Mobile"] = phone
	// 组装JSON字符串
	bytes, _ := json.Marshal(params) // 类似json_encode
	// 组装数组
	var PostData map[string]interface{}
	json.Unmarshal(bytes, &PostData) // 类似json_decode 变数组
	// 获取签名
	sign, stringTime := GetSign(string(bytes))

	// 组装Header
	header := buildHeader(sign, stringTime)
	statusCode, bytes, err := helper.Net{}.Request(ctx, "POST", QueryURL, header, params)

	// 定义请求结构体
	var rsp MallcooMemberQueryRsp
	json.Unmarshal(bytes, &rsp)
	if statusCode != 200 || rsp.Code != 1 || err != nil {
		return errorx.New(rsp.Message, int(rsp.Code))
	}
	return
}
